今天我們把昨天的程式碼整理一下,並且加上新功能:把 PDF 載入,然後產生 embedding 存進去 Qdrant。然後我們再用 RAG 的手法,把問題從向量資料庫抓出來,再透過 ChatGPT 來生成答案。
Langchain 很強的地方,就是有整合裡 Python 生態系裡的許多功能。document_loaders
是載入資料的方式,我們可以透過這裡面的工具,來讀取文件。我們今天要讀取 PDF,還需要安裝 pypdf
,我們使用指令 poetry add pypdf
。
如果你要使用原生的 pypdf
套件也是可以的。事實上如果有更多細節要調整的話,直接使用原生套件才是最好的。不過我們在這裡也是使用 langchain 幫忙整合好的 from langchain.document_loaders import PyPDFLoader
接著我們開始來寫程式碼,建立一個 python 檔叫 langchain_qdrant.py
,先來把所需要套件引入,包括 Langchain、OpenAI、文件載入工具、文字切分器等。
import openai
from langchain.document_loaders import PyPDFLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Qdrant
from langchain.chat_models.azure_openai import AzureChatOpenAI
from langchain.chains import ConversationalRetrievalChain
OPENAI_API_KEY = "yourkey"
OPENAI_EMBEDDING_DEPLOYMENT_NAME = "embedding-ada-002"
OPENAI_EMBEDDING_MODEL_NAME = "text-embedding-ada-002"
OPENAI_DEPLOYMENT_NAME = "gpt-35-16k"
MODEL_NAME = "gpt-35-turbo-16k"
OPENAI_DEPLOYMENT_ENDPOINT = "https://japanopenai2023ironman.openai.azure.com/"
OPENAI_API_TYPE = "azure"
OPENAI_API_VERSION = "2023-03-15-preview"
OpenAIEmbeddings
,貼上以下的程式碼。
def get_embeddings():
return OpenAIEmbeddings(
openai_api_key=OPENAI_API_KEY,
openai_api_base=OPENAI_DEPLOYMENT_ENDPOINT,
openai_api_version=OPENAI_API_VERSION,
openai_api_type=OPENAI_API_TYPE,
deployment=OPENAI_EMBEDDING_DEPLOYMENT_NAME,
model=OPENAI_EMBEDDING_MODEL_NAME,
chunk_size=1
)
def load_and_split_documents(filepath="./pdf/qa.pdf"):
loader = PyPDFLoader(filepath)
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=100)
return text_splitter.split_documents(documents)
我們這裡的 qa.pdf
是抓政府的未滿 2 歲兒童托育補助問答集,可以去下面這個連結下載。
https://magicpandaengineer.blob.core.windows.net/img/2023ironman/qa.pdf
def get_document_store(docs, embeddings):
return Qdrant.from_documents(
docs,
embeddings,
url="http://localhost:6333",
collection_name="PDF_Langchain",
force_recreate=True
)
def get_chat_model():
return AzureChatOpenAI(
openai_api_key=OPENAI_API_KEY,
openai_api_base=OPENAI_DEPLOYMENT_ENDPOINT,
openai_api_type=OPENAI_API_TYPE,
openai_api_version=OPENAI_API_VERSION,
deployment_name=OPENAI_DEPLOYMENT_NAME,
model_name=MODEL_NAME,
)
def ask_question_with_context(qa, question, chat_history):
query = ""
result = qa({"question": question, "chat_history": chat_history})
print("answer:", result["answer"])
chat_history = [(query, result["answer"])]
return chat_history
ConversationalRetrievalChain
這裡的使用方法。
def main():
embeddings = get_embeddings()
docs = load_and_split_documents()
doc_store = get_document_store(docs, embeddings)
llm = get_chat_model()
qa = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=doc_store.as_retriever(),
return_source_documents=True,
verbose=False
)
chat_history = []
while True:
query = input('you: ')
if query == 'q':
break
chat_history = ask_question_with_context(qa, query, chat_history)
if __name__ == "__main__":
main()
以上就是最常見的文件整合 ChatGPT 的應用啦!明天我們繼續來看 Langchain 還有什麼重點。